import styles from './index.less';
import React from 'react';
import { Graph, Addon, Node } from '@antv/x6';
import { Form, Radio, Switch, Slider, Input } from 'antd';
import StartNode from '../flow/startShape';
import flowNode from '../flow/nodeShape';

Graph.registerNode('start-node', StartNode, true);
Graph.registerNode('flow-node', flowNode, true);

type  EditTypeEnum = 'grid' | 'node' | 'line';
export default () => {

  const refDiv = React.useRef<HTMLDivElement>(null);
  const [editType, setEditType] = React.useState<EditTypeEnum>('grid');
  const [graphObject, setGraphObject] = React.useState<Graph>();
  const dndObject = React.useMemo<Addon.Dnd>(() => {
    return new Addon.Dnd({
      target: graphObject as Graph,
      validateNode() {
        return true;
      },
    });
  }, [graphObject]);
  const [formObject] = Form.useForm();

  React.useEffect(() => {
    const graph = new Graph({
      container: refDiv.current as HTMLElement,
      scroller: {
        enabled: true,
        pageVisible: true,
        pageBreak: true,
        pannable: false,
      },
      selecting: true,
      resizing: {
        enabled: (arg: Node<Node.Properties>) => {
          return true;
        },
        preserveAspectRatio: true,
      },
      mousewheel: {
        enabled: true,
        modifiers: ['ctrl', 'meta'],
      },
      height: 600,
      grid: { // 网格设置
        size: 20,      // 网格大小 10px
        visible: true, // 渲染网格背景
        type: 'mesh',
        args: {
          color: '#D0D0D0',
          thickness: 1,     // 网格线宽度/网格点大小
          factor: 10,
        },
      },
      connecting: {
        snap: true,
        allowBlank: false,
        allowLoop: false,
        highlight: true,
        sourceAnchor: {
          name: 'center',
        },
        targetAnchor: 'center',
        connectionPoint: 'anchor',
        router: 'manhattan',
        validateMagnet({ magnet }) {
          return magnet.getAttribute('port-group') !== 'in';
        },
        createEdge() {
          return this.createEdge({
            zIndex: -1,
            attrs: {
              line: {
                stroke: '#808080',
                strokeWidth: 1,
                targetMarker: {
                  name: 'block',
                  args: {
                    size: '6',
                  },
                },
              },
            },
          });
        },
        validateConnection({ targetView, sourceMagnet, targetMagnet }) {

          if (!sourceMagnet || !targetMagnet) {
            return false;
          }
          // 判断目标链接桩是否可连接
          const portId = targetMagnet.getAttribute('port') || '';
          const node = targetView?.cell as Node;
          const port = node.getPort(portId);
          if (!port) {
            return false;
          }

          return true;
        },
      },
    });

    graph.on('blank:click', () => {
      setEditType('grid');
    });

    graph.on('cell:selected', ({ cell }) => {
      let removeBtnCfg;
      if (cell.isEdge()) {
        cell.attr('line', { stroke: 'skyblue', strokeWidth: 3 });
        removeBtnCfg = { distance: '30%' };
        setEditType('line');
      } else if (cell.isNode()) {
        const cellView = graph.findView(cell);
        cellView?.addClass(`${cell.shape}-selected`);
        removeBtnCfg = { x: 0, y: 0, offset: { x: -5, y: -5 } };
        cell.getPorts().map((p) => {
          cell.setPortProp(p.id as string, 'attrs/circle', {
            style: {
              visibility: 'visible',
            },
          });
        });
        setEditType('node');
      }
      cell.addTools({
        name: 'button-remove', // 工具名称
        args: removeBtnCfg, // 工具对应的参数
      });
    });

    graph.on('cell:unselected', ({ cell }) => {
      if (cell.isEdge()) {
        cell.attr('line', { stroke: '#808080', strokeWidth: 1 });
      } else if (cell.isNode()) {
        const cellView = graph.findView(cell);
        cellView?.removeClass(`${cell.shape}-selected`);
        cell.getPorts().map((p) => {
          cell.setPortProp(p.id as string, 'attrs/circle', {
            style: {
              visibility: 'hidden',
            },
          });
        });
      }
      cell.removeTools();
    });

    graph.on('node:mouseenter', ({ node }) => {
      if (graph.isSelected(node)) {
        return;
      }
      node.getPorts().map((p) => {
        node.setPortProp(p.id as string, 'attrs/circle', {
          style: {
            visibility: 'visible',
          },
        });
      });
    });

    graph.on('node:mouseleave', ({ node }) => {
      if (graph.isSelected(node)) {
        return;
      }
      node.getPorts().map((p) => {
        node.setPortProp(p.id as string, 'attrs/circle', {
          style: {
            visibility: 'hidden',
          },
        });
      });
    });

    graph.on('node:resizing', ({ node }) => {
      const size = node.getSize();
      console.log(node.shape);
      if (node.shape === 'start-node') {
        node.setAttrs({
          icon: {
            width: size.width / 2,
            height: size.width / 2,
            x: size.width / 2 - size.width / 4,
            y: size.width / 2 - size.width / 4,
          },
        });
      }
      else if(node.shape === 'flow-node')
      {
        node.setAttrs({
          icon: {
            width: size.height / 2,
            height: size.height / 2,
          },
        });
      }
    });

    setGraphObject(graph);
    return () => {
      graph.dispose();
    };
  }, []);

  const OnFormValuesChange = (changedValues, values) => {
    const { showGrid, gridType, gridSize } = changedValues;
    if (showGrid !== undefined) {
      showGrid ? graphObject?.showGrid() : graphObject?.hideGrid();
    }

    if (gridType !== undefined) {
      graphObject?.drawGrid({
        type: gridType,
      });
    }

    if (gridSize !== undefined) {
      graphObject?.setGridSize(gridSize);
    }
  };

  const startDrag = (e, type) => {
    let node;
    if (type === 'start') {
      node = graphObject?.createNode({
        shape: 'start-node',
      });
    } else {
      node = graphObject?.createNode({
        shape: 'flow-node',
      });
    }
    dndObject.start(node as Node, e);
  };

  return (
    <div className={styles.flowMain}>
      <div className={styles.flowLeftPanel}>
        <ul>
          <li>
            <div className={styles.startNode} onMouseDown={(e) => {
              startDrag(e, 'start');
            }}></div>
            <p>开始</p>
          </li>
          <li>
            <div className={styles.flowNode} onMouseDown={(e) => {
              startDrag(e, 'node');
            }}></div>
            <p>流程节点</p>
          </li>
        </ul>
      </div>
      <div className={styles.flowContainer} ref={refDiv}></div>
      <div className={styles.flowRightPanel}>{editType === 'grid' ? <>
        <div className={styles.flowSetTitle}>画布背景设置</div>
        <div className={styles.flowSetContent}>
          <Form
            form={formObject}
            onValuesChange={OnFormValuesChange}
          >
            <Form.Item label="是否显示网格" name="showGrid" valuePropName="checked">
              <Switch defaultChecked/>
            </Form.Item>
            <Form.Item label="网格类型" name="gridType" initialValue="mesh">
              <Radio.Group>
                <Radio value="mesh">四边</Radio>
                <Radio value="dot">点状</Radio>
              </Radio.Group>
            </Form.Item>
            <Form.Item label="网格大小" name="gridSize" initialValue={20}>
              <Slider max={30} min={0}/>
            </Form.Item>
          </Form>
        </div>
      </> : <></>}
        {editType === 'line' ? <>
          <div className={styles.flowSetTitle}>线条设置</div>
          <div className={styles.flowSetContent}>
            <Form
              form={formObject}
              onValuesChange={OnFormValuesChange}
            >
              <Form.Item label="线条文本" name="lineText">
                <Input placeholder="请输入线条文本"/>
              </Form.Item>
              <Form.Item label="线条类型" name="lineType" initialValue="mesh">
                <Radio.Group>
                  <Radio value="mesh">四边</Radio>
                  <Radio value="dot">点状</Radio>
                </Radio.Group>
              </Form.Item>
              <Form.Item label="线条大小" name="gridSize" initialValue={20}>
                <Slider max={30} min={0}/>
              </Form.Item>
            </Form>
          </div>
        </> : <></>}

        {editType === 'node' ? <>
          <div className={styles.flowSetTitle}>节点设置</div>
          <div className={styles.flowSetContent}>
            <Form
              form={formObject}
              onValuesChange={OnFormValuesChange}
            >
              <Form.Item label="节点文本" name="nodeText">
                <Input placeholder="请输入节点文本"/>
              </Form.Item>
              <Form.Item label="字体大小" name="nodeTextSize" initialValue={12}>
                <Slider max={20} min={10}/>
              </Form.Item>
            </Form>
          </div>
        </> : <></>}
      </div>
    </div>
  );
}
